import numpy as np
import cv2 as cv
import os
from functools import cache


class CornerDetectMethodBase:
    def __init__(self, input_fig: np.ndarray, axis_0: int = 0, *args, **kwargs) -> None:
        """
        Arguments:
          - `input_fig`: 输入图像的矩阵
          - `axis_0`: 输入图像的像素坐标轴起点，python可取为0，matlab一般是1
        """
        self._fig = input_fig
        self._axis_0 = axis_0
        self._fig_height, self._fig_width = self.fig.shape
        print("*" * 20)
        print(f"Here is the result of {self._name} mothod corner detection:")
        print("|方法名称|横坐标中心/pix|纵坐标中心/pix|")
        print("|:--:|:--:|:--:|")

    def run(
        self,
        output_path: os.PathLike,
        x0,
        y0,
        img_resized=None,
        zoom: bool = False,
        *args,
        **kwargs,
    ):
        if not os.path.exists(output_path):
            os.mkdir(output_path)
        x_c, y_c = self._process(*args, **kwargs) if not x0 and not y0 else x0, y0
        resize_k = 30
        if zoom:
            output_window = 10
            if not isinstance(img_resized, np.ndarray):
                img_resized = cv.resize(
                    self.fig[
                        self.width // 2
                        - output_window : self.width // 2
                        + output_window
                        + 1,
                        self.height // 2
                        - output_window : self.height // 2
                        + output_window
                        + 1,
                    ],
                    None,
                    fx=resize_k,
                    fy=resize_k,
                    interpolation=cv.INTER_LINEAR,
                )
                cv.imwrite(
                    os.path.join(output_path, f"result_{self._name}.png"), img_resized
                )
                img_resized = cv.imread(
                    os.path.join(output_path, f"result_{self._name}.png"),
                    cv.IMREAD_COLOR,
                )
            print(f"|{self._name}|{x_c:.4f}|{y_c:.4f}|")
            cv.drawMarker(
                img_resized,
                (
                    int(
                        resize_k
                        * (x_c + self.axis_0 - self.width // 2 + output_window + 1)
                    ),
                    int(
                        resize_k
                        * (y_c + self.axis_0 - self.height // 2 + output_window + 1)
                    ),
                ),
                (0, 0, 255),
                cv.MARKER_CROSS,
                1,
                5,
                cv.LINE_AA,
            )
            cv.putText(
                img_resized,
                f"x_c = {x_c:.4f}",
                (
                    int(
                        resize_k
                        * (x_c + self.axis_0 - self.width // 2 + output_window + 1)
                    ),
                    int(
                        resize_k
                        * (y_c + self.axis_0 - self.height // 2 + output_window + 1)
                    )
                    + 2 * resize_k,
                ),
                cv.FONT_HERSHEY_SIMPLEX,
                1,
                (0, 0, 255),
                1,
                cv.LINE_AA,
            )
            cv.putText(
                img_resized,
                f"y_c = {y_c:.4f}",
                (
                    int(
                        resize_k
                        * (x_c + self.axis_0 - self.width // 2 + output_window + 1)
                    ),
                    int(
                        resize_k
                        * (y_c + self.axis_0 - self.height // 2 + output_window + 1)
                    )
                    + 4 * resize_k,
                ),
                cv.FONT_HERSHEY_SIMPLEX,
                1,
                (0, 0, 255),
                1,
                cv.LINE_AA,
            )
            cv.imwrite(
                os.path.join(output_path, f"result_{self._name}.png"), img_resized
            )
            return img_resized
        else:
            if not isinstance(img_resized, np.ndarray):
                img_resized = cv.resize(
                    self.fig,
                    None,
                    fx=resize_k,
                    fy=resize_k,
                    interpolation=cv.INTER_LINEAR,
                )
                cv.imwrite(
                    os.path.join(output_path, f"result_{self._name}.png"), img_resized
                )
                img_resized = cv.imread(
                    os.path.join(output_path, f"result_{self._name}.png"),
                    cv.IMREAD_COLOR,
                )
            print(f"|{self._name}|{x_c:.4f}|{y_c:.4f}|")
            cv.drawMarker(
                img_resized,
                (
                    int(resize_k * (x_c + self.axis_0 + 1)),
                    int(resize_k * (y_c + self.axis_0 + 1)),
                ),
                (0, 0, 255),
                cv.MARKER_CROSS,
                1,
                5,
                cv.LINE_AA,
            )
            cv.putText(
                img_resized,
                f"x_c = {x_c:.4f}",
                (
                    int(resize_k * (x_c + self.axis_0 + 1)),
                    int(resize_k * (y_c + self.axis_0 + 1)) + 2 * resize_k,
                ),
                cv.FONT_HERSHEY_SIMPLEX,
                1,
                (0, 0, 255),
                1,
                cv.LINE_AA,
            )
            cv.putText(
                img_resized,
                f"y_c = {y_c:.4f}",
                (
                    int(resize_k * (x_c + self.axis_0 + 1)),
                    int(resize_k * (y_c + self.axis_0 + 1)) + 4 * resize_k,
                ),
                cv.FONT_HERSHEY_SIMPLEX,
                1,
                (0, 0, 255),
                1,
                cv.LINE_AA,
            )
            cv.imwrite(
                os.path.join(output_path, f"result_{self._name}.png"), img_resized
            )
            return img_resized

    @property
    def fig(self):
        return self._fig

    @property
    def height(self):
        return self._fig_height

    @property
    def width(self):
        return self._fig_width

    @property
    def axis_0(self):
        return self._axis_0

    @property
    def _name(self):
        raise NotImplementedError

    def _process(self, *args, **kwargs):
        raise NotImplementedError
